import 'package:dio/dio.dart';
import 'package:get/get.dart' hide Response;
import 'package:sainbainu/common/http/config.dart';
import 'package:sainbainu/common/http/exception.dart';
import 'package:sainbainu/common/services/user.dart';
import 'package:sainbainu/common/routes/routes.dart';

class RetryTokenInterceptor extends Interceptor {
  Dio? dio;
  bool _isRefreshing = false;
  final List<Function> _retryQueue = [];

  RetryTokenInterceptor();

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) async {
    Map<String, dynamic> data = response.data;
    if (data['code'] == 402) {
      RequestOptions options = response.requestOptions;

      // 创建一个新的Dio实例，避免循环依赖
      dio ??= Dio();

      if (_isRefreshing) {
        // 如果已经在刷新token，则将请求加入队列等待刷新完成
        // _retryQueue.add(() => _retryRequest(options));
        _retryQueue.add(
          () async => handler.resolve(await _retryRequest(options)),
        );
      } else {
        // 否则，开始刷新token
        _isRefreshing = true;

        try {
          await _refreshToken();
          // 刷新token成功后，重试队列中的请求
          for (var callback in _retryQueue) {
            callback();
          }
          _retryQueue.clear();
        } on CustomHttpException catch (e) {
          // 如果刷新token失败，清空队列
          _retryQueue.clear();
          handler.reject(DioException(
            requestOptions: options,
            error: e,
          ));
          return;
        } finally {
          _isRefreshing = false;
        }
      }
      try {
        // 当前请求加入队列等待刷新完成
        var res = await _retryRequest(options);
        return handler.resolve(res);
      } on CustomHttpException catch (e) {
        return handler.reject(DioException(
          requestOptions: options,
          error: e,
        ));
      }
    } else {
      return handler.next(response);
    }
  }

  /// 刷新 token
  Future<void> _refreshToken() async {
    try {
      final loginRes = await dio!.post(
        '${HttpConfig.baseUrl}/api/login/renew_token',
      );
      if (loginRes.data['code'] != 200) {
        // 清空登录信息
        UserService.to.setIsLogin(false);
        UserService.to.setToken(null);
        Get.toNamed(AppRoutes.login);
        throw Exception(loginRes.data['msg'] ?? '重新登录失败');
      } else {
        // 保存新的访问令牌
        String accessToken = loginRes.data['data']['token'];
        UserService.to.setIsLogin(true);
        UserService.to.setToken(accessToken);
        UserService.to.getAccountInfo();
      }
    } on DioException catch (e) {
      CustomHttpException httpException = CustomHttpException.create(e);
      throw httpException;
    } catch (e) {
      throw CustomHttpException(message: e.toString());
    }
  }

  /// 重新请求失败的请求
  Future<Response> _retryRequest(RequestOptions options) async {
    try {
      // 更新请求头的token
      options.headers['Authorization-Social-APP'] =
          'Bearer ${UserService.to.token}';
      var res = await dio!.fetch(options);
      if (res.data['code'] != 200) {
        throw Exception(res.data['msg'] ?? '重试失败');
      }
      return res;
    } on DioException catch (e) {
      CustomHttpException httpException = CustomHttpException.create(e);
      throw httpException;
    } catch (e) {
      throw CustomHttpException(message: e.toString());
    }
  }
}
